#pragma once
#include "Thread.hpp"
#include <queue>
#include <vector>
#include "LOG.hpp"

using namespace ns_thread;

template <class T>
class ThreadPool
{
private:
    void Lock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&_mutex);
    }

    void Sleep()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }
    void Wakeup()
    {
        pthread_cond_signal(&_cond);
    }
    void WakeAll()
    {
        pthread_cond_broadcast(&_cond);
    }
public:
    ThreadPool(int nums)
    :_threadnums(nums)
    ,_waitnums(0)
    ,_isrunning(false)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        LOG(INFO,"Thread_pool Construct Success");
    }

    //不设置成static了，换种写法
    void HandlerTask(std::string name)
    {
        LOG(INFO,"%s enter HandlerTask",name.c_str());
        Lock();
        while(1)
        {
            //任务为空 && 线程池正在运行
            while(_queue.empty() && _isrunning)
            {
                _waitnums++;
                Sleep();      //因为下面Stop的做法，以后所有在这里被唤醒的线程，因为_isrunning = false，继续向下执行，从而进行任务调用
                _waitnums--;
            }
            //任务为空 && 线程池结束了
            if(_queue.empty() && !_isrunning)
            {
                Unlock();
                break;
            }
            //任务不为空 && 线程池正在运行————正常从任务队列里取任务，并且调用。
            //任务不为空 && 线程池没有运行————必须让线程池启动，处理完所有存在的任务！然后再退出

            T out = _queue.front();
            _queue.pop();
            Unlock();
            // 处理任务,这个任务属于这个线程独占的任务，不属于共享资源了。
            LOG(INFO,"%s thread handle task",name.c_str());
            out();
            LOG(INFO,"%s thread handle task,result is: %s",name.c_str(),out.Result().c_str());
        }
    }

    void InitThreadPool()
    {
        for(int i = 0;i<_threadnums;i++)
        {
            std::string name = "Thread-" + std::to_string(i+1);
            _threads.emplace_back(std::bind(&ThreadPool::HandlerTask,this,std::placeholders::_1),name);
        }
        _isrunning = true;
    }

    void Start()
    {
        for(auto& thread : _threads)
        {
            thread.start();
            LOG(INFO,"%s Start Success",thread.name().c_str());
        }

    }

    void Stop()
    {
        Lock();
        _isrunning = false;
        //唤醒线程去完成队列里剩下的任务
        WakeAll();

        Unlock();
    }

    void Wait()
    {
        for(auto& thread : _threads)
        {
            thread.Join();
            LOG(INFO,"%s Join Success",thread.name().c_str());

        }
    }
    //向任务队列push任务
    bool Push(const T& in)
    {
        Lock();
        bool ret = false;
        if(_isrunning)
        {
            _queue.push(in);
            LOG(INFO,"task push success");
            //有任务，唤醒一个线程
            if(_waitnums > 0)
                Wakeup();
            ret = true;
        }
        Unlock();
        return ret;
    }

   
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        LOG(INFO,"threads Destory success");
    }

private:
    int _threadnums;
    std::vector<Thread> _threads;
    std::queue<T> _queue;   //任务队列
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    int _waitnums;
    bool _isrunning;
};